package com.marco.ipdata.service.impl;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.marco.IPUtils;
import com.marco.commons.BeanMapper;
import com.marco.ipdata.dao.IPBaseDao;
import com.marco.ipdata.domain.IPBase;
import com.marco.ipdata.domain.PureSupply;
import com.marco.ipdata.service.IPBaseService;
import com.marco.system.service.ChinaAdInfoService;
import com.marco.system.service.NormalizationService;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.sql.Timestamp;
import java.util.*;

/**
 * ChinaIPServiceImpl.java
 * Create on 2017/3/23
 * Copyright(c) JD Inc 2017. All Rights Reserved.
 * <pre>
 * 功能说明：
 * </pre>
 */
@Service
@Transactional
public class IPBaseServiceImpl implements IPBaseService {
    private static final Logger logger = LoggerFactory.getLogger(IPBaseServiceImpl.class);
    @Autowired
    private ChinaAdInfoService chinaAdInfoService;
    @Autowired
    private NormalizationService normalizationService;
    @Autowired
    private IPBaseDao ipBaseDao;


    @Override
    public void batchSave(String tableName, List<IPBase> list) {
        try {
//            logger.info("正在更新表 {} 中 IP数据", tableName);
            ipBaseDao.batchSaveByTableName(tableName, list);
        } catch (Exception e) {
            throw new RuntimeException("批量插入数据出现异常", e);
        }
    }

    @Override
    public IPBase getBestResult(String ip, String city) {
        try {
            List<IPBase> rsList;
            if (StringUtils.isNotBlank(city)) {
                rsList = ipBaseDao.getAllApisData(ip, city);
                if (CollectionUtils.isEmpty(rsList)) {
                    return null;
                }
                //设置ISP
                String isp = "";
                for (IPBase ipBase : rsList) {
                    if (!ipBase.getIsp().equals("未知")) {
                        isp = ipBase.getIsp();
                        break;
                    }
                }
                //返回结果
                IPBase res = rsList.get(0);
                res.setIsp(isp);
                return res;
            } else {
                rsList = ipBaseDao.getAllApisData(ip, null);
                //按照投票制进行返回最优值
                Integer size = rsList.size();
                for (int i = 0; i < size - 1; i++) {
                    for (int j = i + 1; j < size; j++) {
                        IPBase A = rsList.get(i);
                        IPBase B = rsList.get(j);
                        if (A.equals(B)) {
                            IPBase tmp = A.getAdMerged(B);
                            tmp.setSource(A.getSource() + B.getSource());
                            rsList.set(i, tmp);
                        }
                    }
                }
                Collections.sort(rsList, new Comparator<IPBase>() {
                    @Override
                    public int compare(IPBase o1, IPBase o2) {
                        return o1.getSource().length() > o2.getSource().length() ? -1 : 1;
                    }
                });
                IPBase result = null;
                for (IPBase ipBase : rsList) {
                    if (!ipBase.getProvinceId().equals("0")) {
                        result = ipBase;
                        break;
                    }
                    result = ipBase;
                }
                return result;
            }
        } catch (Exception e) {
            logger.error("查询出现异常、请检查", e);
        }
        return null;
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void processPureData(File file) {
        String tableName = "api_ip_pure";
        LineIterator iterator = null;
        try {
            if (!file.exists() || !file.canRead()) {
                return;
            }
            iterator = FileUtils.lineIterator(file, "GBK");
            //纯真数据有部分脏数据，需要进行纠正
            logger.info("正在获取纯真补充地址、、、、、");
            Map<String, String> supplyMap = this.getPureSupplyMap();
            logger.info("准备更新纯真数据，请稍候、、、、、");
            List<IPBase> ipBaseList = Lists.newArrayList();
            while (iterator.hasNext()) {
                String line = iterator.nextLine();
                Scanner sc = new Scanner(line);
                String ipMin = sc.next();
                String ipMax = sc.next();
                //解析IP段对应地址
                String ipLocation = sc.next().trim();
                if (StringUtils.isNotBlank(supplyMap.get(ipLocation))) {
                    ipLocation = supplyMap.get(ipLocation);
                }
                //解析IP段对应运营商sc
                String ipMore;
                if (sc.hasNext()) {
                    ipMore = sc.next().trim().replaceAll(" ", "");
                } else {
                    ipMore = "未知";
                }
                IPBase ipBase = normalizationService.formatAdStr(ipLocation, chinaAdInfoService.getJdChinaMap());
                if (ipBase != null) {
                    ipBase.setSource("4");
                    ipBase.setTableName(tableName);
                    ipBase.setIsp(normalizationService.formatISP(ipMore));
                    ipBase.setUpdateDateTime(new Timestamp(DateTime.now().getMillis()));
                    //将IP段拆分成前三段的IP，
                    List<String> ipLists = IPUtils.listIPWithThreeSeg(ipMin, ipMax);
                    for (String ip : ipLists) {
                        IPBase tmp = new IPBase();
                        BeanMapper.copy(ipBase, tmp);
                        tmp.setIp(ip);
                        ipBaseList.add(tmp);
                        if (ipBaseList.size() > 1000 || !iterator.hasNext()) {
                            this.batchSave(tableName, ipBaseList);
                            ipBaseList.clear();
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("处理纯真数据出现异常，请检查", e);
        }
    }

    @Override
    public Map<Long ,Map<Long,IPBase>> processIPIPData(File file) {
        LineIterator iterator = null;
        Map<Long ,Map<Long,IPBase>> ipipTable = Maps.newHashMap();
        try {
            if (!file.exists() || !file.canRead()) {
                return null;
            }
            logger.info("正在处理IPIP数据，请稍候、、、、、");
            iterator = FileUtils.lineIterator(file);
            while (iterator.hasNext()) {
                String line = iterator.nextLine();
                String[] strs = line.split("\t");
                if ((IPUtils.toDecimal(strs[0])) % 256 != 0) {
                    continue;
                }
                long ipMin = IPUtils.toDecimal(strs[0]);
                long ipMax = IPUtils.toDecimal(strs[1]);
                String nation = strs[2].replace("*", "未知");
                String province = strs[3].replace("*", "未知").replace("中国", "未知");
                String city = strs[4].replace("*", "未知");
                String isp = strs[6].replace("*", "未知");
                //排除脏数据
                List<String> badData = this.getIPIPBadData();
                if (badData.contains(nation)) {
                    continue;
                }
                IPBase ipBase;
                if (nation.equals("中国")) {
                    ipBase = normalizationService.formatAdStr(province + city, chinaAdInfoService.getJdChinaMap());
                    if (ipBase == null) {
                        IPBase.Builder builder = new IPBase.Builder();
                        builder.nation(nation).nationId("0").province("未知").provinceId("0").city("未知").cityId("0")
                                .district("未知").districtId("0");
                        ipBase = new IPBase(builder);
                    }
                } else {
                    IPBase.Builder builder = new IPBase.Builder();
                    builder.nation(nation).nationId("-1").province("未知").provinceId("-1").city("未知").cityId("-1")
                            .district("未知").districtId("-1");
                    ipBase = new IPBase(builder);
                }
                //运营商
                ipBase.setIsp(isp);
                Map<Long ,IPBase> result = Maps.newHashMap();
                result.put(ipMax,ipBase);
                ipipTable.put(ipMin, result);
            }
            logger.info("处理IPIP数据完成，请检查、、、、");
        } catch (Exception e) {
            logger.error("存储IPIP数据出现异常", e);
        } finally {
            LineIterator.closeQuietly(iterator);
        }
        return ipipTable;
    }

    @Override
    public List<String> getIPIPBadData() {
        try {
            return ipBaseDao.getIPIPBadData();
        } catch (Exception e) {
            throw new RuntimeException("获取IPIP脏数据出现异常", e);
        }
    }

    /**
     * 获取纯真的处理后补充地址，纠正纯真数据中的错别字等问题地址
     * 数据存储在api_ip_pure_supply表中
     *
     * @return
     */
    private Map<String, String> getPureSupplyMap() {
        Map<String, String> res = Maps.newHashMap();
        try {
            List<PureSupply> list = ipBaseDao.getSupplies();
            for (PureSupply supply : list) {
                res.put(supply.getOldAd(), supply.getNewAd());
            }
        } catch (Exception e) {
            throw new RuntimeException("获取纯真补充地址出现异常", e);
        }
        return res;
    }
}
